package com.flyiu.data.consistency.config;

import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

//@Configuration
@ConditionalOnProperty(prefix = "spring.datasource", name = "url")
public class DataSourceConfig {

    @Autowired
    private JpaProperties                   jpaProperties;

    @Autowired
    private HibernateProperties             hibernateProperties;
    @Autowired
    private ConfigurableListableBeanFactory beanFactory;
    @Primary
    @Bean(name = "dataSourceProperties")
    @Qualifier("dataSourceProperties")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Primary
    @Bean(name = "datasources")
    @Qualifier("datasources")
    @ConditionalOnMissingBean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource(@Qualifier("dataSourceProperties") DataSourceProperties dataSourceProperties) {
        return dataSourceProperties.initializeDataSourceBuilder().build();
    }

    @Bean(name = "entityManagerFactory")
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactory( DataSource dataSource,EntityManagerFactoryBuilder builder) {
        Map<String, Object> properties = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
        return builder.dataSource(dataSource).packages(getPackagesToScan()).persistenceUnit("primaryatasourceUnit").properties(properties).build();

    }

    protected String[] getPackagesToScan() {
        if (AutoConfigurationPackages.has(this.beanFactory)) {
            List<String> basePackages = AutoConfigurationPackages.get(this.beanFactory);
            return basePackages.toArray(new String[basePackages.size()]);
        }
        return new String[0];
    }

    @Bean
    @Primary
    public EntityManager entityManager(DataSource dataSource,EntityManagerFactoryBuilder builder) {
        return entityManagerFactory(dataSource,builder).getObject().createEntityManager();
    }

    /**
     * 事务管理器
     */
    @Primary
    @Bean
    PlatformTransactionManager transactionManager(DataSource dataSource,EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactory(dataSource,builder).getObject());
    }

}
